OSpre——Linux系统

OSpre——Linux系统 1.Linux文件系统 Linux文件系统的最顶层是根目录,用/表示,所有文件都存放在根目录下 根目录下放置的二级目录: /boot目录:启动Linux内核 /etc目录:系统配置文件 /home目录:存放普通用户主目录 /root目录:系统管理员(root用户)主目录 /usr目录:用户系统资源存放的目录 … ~是当前用户主目录的简写 对于一般用户,主目录为/home/用户名 对于root用户,主目录为/root 命令行前符号$代表当前用户为普通用户,#代表当前用户为root用户’ 2.Linux基础命令 1.目录操作 1. cd —— change dictionary cd:切换到某个目录,支持绝对路径和相对路径 用法:cd [参数] 目录 .代表当前目录,..代表上一级目录 cd -切换到上一次访问的目录 cd ~回到当前用户主目录 tab键自动补全 例:下面哪些命令可以切换到 /home/git/test 这个目录?假定你的用户名是 git,你目前所处的目录是 /home/git 答:cd test | cd ~/test | cd ./test | cd test/ 2. ls —— list dictionary contents ls:列出目录中的文件 用法:ls [参数] [目录] 参数: -a 列出隐藏的文件 -l每行只列出一个文件 目录:若未给出则列出当前目录下文件 3. mkdir —— make ditionary mkdir:创建新目录 用法: mkdir [参数] 目录 ...

February 21, 2024 · 1 min · sudo

从0开始配龙芯杯vivado+vcs虚拟机环境(Ubuntu22.04)

从0开始配龙芯杯vivado+vcs虚拟机环境(Ubuntu22.04) 0. mad ​ 为了配置龙芯杯需要的vivado+vcs环境,这个繁琐的过程已经困扰了我两天,重新装了三次虚拟机系统,总结之后决定在配置的过程中写一篇笔记来记录过程,如果这次失败了也方便下一次再来。一开始我采用Ubuntu23.10,后来遇到各种不理解的报错,不知道怎么解决,我就都归结到Ubuntu版本过新上(恼),于是换成Ubuntu22.04镜像文件重新配置(QAQ),(后来发现确实是因Ubuntu版本有一定问题),所以一定要用Ubuntu22.04啊!!! 环境的软件版本: Vmware Workstation Pro 17 Ubuntu 22.04 vivado 2019.2 vcs 2018.09 1.虚拟机初始配置 1.配置中文输入法 ​ 一个新系统自然要先配置好中文输入法,我这里使用ibus框架。 1.安装汉语支持 ​ Settings——>Region&Language——>Manage Install Language——>Install/Remove Languages——>Chinese(simplified)——>重启系统 2.安装ibus框架 sudo apt-get install ibus sudo apt-get install ibus-pinyin sudo ibus-setup#打开ibus设置界面 ​ 在打开的ibus设置界面中在Input Method一栏中添加中文输入法Add——>Chinese——>Intelligent Pinyin 3.设置系统变量 vim ~/.bashrc #添加系统变量 export GTK_TM_MODULE=ibus export XMODIFIERS=@im=ibus export QT_IM_MODULE=ibus ############ source .bashrc 再次重启使系统变量生效 4. add Input Source settings——>Keyboard——>Input Source——>add Chinese(Intelligent Pinyin) 再次重启即可使用中文输入法 2.安装vmware-tools ​ vmware-tools是实现主机与虚拟机之间交互的重要软件,网上一些教程通过vmware station上方虚拟机选项卡中的重新安装vmware tools进行。我们可以发现此时该选项为灰色,即使通过网络上的种种办法可以改为黑色可选状态,但在安装过程中会报错Segmentation fault,实际原因是下载的版本过低,与当前系统不适配,我们使用手动命令行下载可以避免 ...

February 8, 2024 · 3 min · sudo

P7-design-document

P7-Design-Document 0.顶层设计概述 ​ P7要求为实现MIPS微系统,需要为P6实现的流水线CPU添加异常中断功能,并封装为CPU模块、实现系统桥Bridge、计时器Timer1,Timer2等模块,最终形成MIPS微系统,如下图所示。 绿色虚线表示已经实现 紫色虚线表示新增部分 红色虚线为改变后的DM接口 P7需要实现的任务如下列表 任务 解释 计时器 课程组提供代码 系统桥 为CPU提供统一的访问外设的接口,自行实现 协处理器CP0 设置CPU的异常处理功能,反馈CPU的异常信息,自行实现 内部检测异常与流水 CPU检测内部指令执行错误 外部中断响应 CPU需要具有响应外部中断信号的能力 异常处理指令 异常处理程序中,会有一些特殊的指令需要实现 单周期CPU的封装 让CPU从外部看上去是单周期CPU 异常处理程序 利用MARS编写简单的异常处理程序进行测试 施工步骤: 更改流水线各级使之可以产生异常 添加CP0处理异常 添加Bridge与两个外设 异常与中断 异常:内部异常 如F级取指异常、D级计算溢出等 中断:来自外部设备,Timer0,Timer1,Interrupt 来自外部设备的中断比内部异常优先级更高 一.功能部件设计 0.新增指令的实现思路 P7中增加四条指令 mtc0 mfc0 eret syscall mtc0 :写入CP0中寄存器(12/14) 对于mtc0和mfc0指令 : 读取的CP0寄存器地址均为rd域,由于本实现中采用了集中式译码,故增加数据通路,将原指令的rd域流水下去,作为CP0寄存器地址, CP0_addr 指令格式 : 010000 || 00100 || rt || rd || 00000000000 mtc0 rt,rd MCU : CP0_WE_D T_rs_use = T_rt_use = 3(这里rt的真实使用时间是3,但是并不会对暂停/转发造成影响,Tuse >= Tnew成立,可以通过转发解决) T_new = 0 写入时应当注意 :Cause寄存器(13)不允许写入,EPC允许写入,SR寄存器部分字段允许写入,其他不允许写入的字段要保持为0 ...

December 3, 2023 · 11 min · sudo

P6课上测试

P6课上测试 ​ P6课上测试内容与P5课上测试内容大概只有第一题计算类型上的区别,变为考察乘除槽的指令 一.增添指令一般步骤 读懂RTL语言,注意opcode与funct位置,是什么类型的指令,会不会与已经添加过的指令发生冲突(例如P5上机第一题中计算指令与slt指令opcode重复QAQ) 使用课上提供的.class文件在MARS中进行模拟 计算指令是否可以进行归类,cal_R,cal_I;条件跳转指令和条件存储指令一般直接使用check信号对新信号进行特判。 在MCU中从上到下观察是否将新指令加入有效列表 明确新指令的T_use,T_new 二.题型分析 1.涉及到乘除槽的计算类指令 ​ P6的计算指令会涉及到乘除模块,以madd,maddu,msub,msubu等指令为例。 madd : 将两个有符号数相乘,计算结果与之前的HI,LO寄存器中的值相加,而不是覆盖 mddu:将两个无符号数相乘,计算结果与之前的HI,LO寄存器中的值相加,而不是覆盖 msub:将两个有符号数相乘,之前HI,LO中的值减去当前结果 msubu:将两个无符号数相乘,之前HI,LO中的值减去当前结果 1.verilog中的符号性问题 ​ $signed()关键字的功能为数据如何进行补位,根据递归确定外层+向内传播的表达式符号确定规则,例如在P1中遇到的三目表达式中有无符号数导致整个表达式变为无符号的情况。 算数(符号)右移表达式中移位立即数不必要声明为有符号 :$signed(A) »> B 为避免$singed()出现的问题,可以使用位扩展进行代替 1 {{16{imm[15]}},imm}//16位imm符号扩展为32位 2.计算指令中的符号乘除 mult 使用位拼接运算 1 {tmpHI,tmpLO} <= $signed(A) * $signed(B) madd 错误写法1 1 {tmpHI,tmpLO} <= {tmpHI,tmpLO} + $signed(A)*$signed(B) 位拼接运算{tmpHI,tmpLO}默认被当作无符号数,向内传播导致$signed(A)*$signed(B)变为无符号的 修改为: 1 {tmpHI,tmpLO} <= $signed({tmpHI,tmpLO}) + $signed(A)*$signed(B) 错误写法2 1 {tmpHI,tmpLO} <= {tmpHI.tmpLO} + $signed($signed(A)*$signed(B)) 使用$signed()屏蔽了外界符号性的传入,同时屏蔽了位宽信息的传入,由于$signed(A),$signed(B)为32位,则$signed($signed(A)*$signed(B))为32位 ...

December 2, 2023 · 4 min · sudo

P6-design-document

P6-Design-Document 一.数据通路图示 ​ P6在P5的基础上新增乘除槽单元、字节使能单元、数据扩展单元,在顶层模块中增加与testbench的接口,将IM与DM外移到testbench中。 二.功能模块定义 1. MCU 1.端口定义列表 名称 方向 位宽 描述 D_opcode I 6 操作码 D_funct I 6 功能码 SelA3_D O 2 选择写入寄存器地址 RegWrite_D O 1 寄存器堆写入地址 EXTOp_D O 1 立即数扩展信号 SelEMout_D O 1 选择E、M级转发数据 SelWout_D O 2 选择W级转发数据/写入GRF数据 SeLALUB_D O 1 选择ALU_B端口输入数据 SelALUS_D O 1 选择ALU_S端口移位数据 check_D O 1 判定是否为新信号(课上扩展使用) mf_D O 1 mfhi/mflo指令,选择E级输出数据 start_D O 1 乘除类导致延迟的指令信号,只有md类需要 CMPOp_D O 3 B类跳转指令操作码 NPCOp_D O 3 跳转地址选择 ALUOp_D O 4 ALU计算操作 MDUOp_D O 4 乘除类计算操作 DMOp_D O 4 存取指令操作 T_rs_use_D O 2 位于D级用到rs寄存器中值的周期数 T_rt_use_D O 2 位于D级用到rt寄存器中值的周期数 T_new_D O 2 位于D级产生新信号的周期数 注:由于BE模块产生字节使能信号,将原内存写入使能信号MemWrite省去 ...

November 28, 2023 · 11 min · sudo

P5课上测试

P5课上测试 一.增添指令一般步骤 明确指令RTL,可以使用课上提供的.class文件进行模拟 明确非转发数据通路:可以在单周期中思考新指令的行为,构思出数据通路 考虑转发: 考虑GRF的五位写入地址是否正确,一般在第二步已经调整完毕,但是像lwer,lhso等条件存储类指令只有在M级中从DM中取出数据后才能明确写入地址,需要在M级将写入地址再次修改 明确新指令的T_rs_use,T_rt_use,T_new,用不到的寄存器设置为T_rs/rt_use = 3 二.课上测试题型分析 1.计算指令——在E级就可以完成所有操作 ​ 新增的计算指令一般只需要增加ALU的功能,但是计算行为会稍稍复杂一些,Tnew和Tuse与calc_R或calc_I型保持一致即可 例如 循环左移 1 2 if(B[4:0] == 5'b0) out = A; else out = A << B[4:0] | A >> (6'd32 - B[4:0]) 2.条件跳转类——在D级就可以完成所有操作 条件跳转 + 无条件链接 条件跳转 + 条件链接 条件跳转 + 条件(无条件)链接 + 不跳转时清空延迟槽 1.条件跳转 增加CMP中的判断功能 2.无条件链接 D级将RegWrite置为1,跟随流水并更改A3(31),最后在W级选择PC8作为写入数据 3.条件链接 在D级根据CMP模块的输出结果判断RegWrite是否有效 设置一个check信号用以确定当前指令是否为新指令,进行流水 1 2 3 4 5 6 7 wire D_RegWrite_new = check_D ? (D_CMP_out ? 1'b1 : 1'b0) : RegWrite_D; //判断是否为新信号 如果是就已经隐含着regwrite=1,只需对CMP结果进行判断 //如果不是就保留原信号 //uut E_reg top_e_reg( .RegWrite_D(D_RegWrite_new), ); 4.不跳转时清空延迟槽 根据CMP输出结果判断是否要清空D级流水寄存器(这就是hyggge学长P5教程中D级clr信号接口的原因QAQ) 注意:当前为stall状态则不能清空延迟槽,此时传入CMP模块的不是新值,判断无效 1 2 3 4 5 wire D_reg_clr = check_D & ~D_CMP_out & ~stall //新信号 & 不跳转 & 不暂停 D_reg top_d_reg( .D_clr(D_reg_clr) //加入到同步复位列表中 ); 3.条件存储类——在M级就可以完成所有操作 在原来基础上修改stall控制信号,如果D级的指令要读寄存器,而且后面的新指令可能要写这个寄存器,那么就stall 修改写入A3地址并传入W_reg和HCU 1. condition1 condition成立 :将DM中值写入A condition不成立 :将DM中值写入B 1 2 3 4 5 6 7 8 9 10 11 12 13 14 //第一种题型(eg:condition满足向rt号写,否则写31号) assign stall_rs_E = (D_A1 != 5'd0) & (check_E ? (D_A1 == E_A3 | D_A1 == 5'd31) : D_A1 == E_A3) & (RFWrite_E) & (Tuse_rs < Tnew_E); assign stall_rs_M = (D_A1 != 5'd0) & (check_M ? (D_A1 == M_A3 | D_A1 == 5'd31) : D_A1 == M_A3) & (RFWrite_M) & (Tuse_rs < Tnew_M); assign stall_rt_E = (D_A2 != 5'd0) & (check_E ? (D_A2 == E_A3 | D_A2 == 5'd31) : D_A2 == E_A3) & (RFWrite_E) & (Tuse_rt < Tnew_E); assign stall_rt_M = (D_A2 != 5'd0) & (check_M ? (D_A2 == M_A3 | D_A2 == 5'd31) : D_A2 == M_A3) & (RFWrite_M) & (Tuse_rt < Tnew_M); //更改写入寄存器地址(eg:condition满足向rt号写,否则写31号) wire M_A3_new = check_M ? (condition ? `rt : 5'd31) : M_A3; //uut W_reg top_w_reg( .M_A3(M_A3_new), ); HCU top_hcu( .M_A3(M_A3_new), ); 2.condition2 conditon成立 :向31号写 condition不成立 :不写(写入0号寄存器) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 //按照第一种题型以写成 (check_M ? (D_A2 == 5'd31 | D_A2 == 5'd0): D_A2 == M_A3),因为前面有条件 D_A2 != 5'd0,所以可以简化 assign stall_rs_E = (D_A1 != 5'd0) & (check_E ? D_A2 == 5'd31 : D_A2 == M_A3) & (RFWrite_E) & (Tuse_rs < Tnew_E); assign stall_rs_M = (D_A1 != 5'd0) & (check_M ? D_A2 == 5'd31 : D_A2 == M_A3) & (RFWrite_M) & (Tuse_rs < Tnew_M); assign stall_rt_E = (D_A2 != 5'd0) & (check_E ? D_A2 == 5'd31 : D_A2 == M_A3) & (RFWrite_E) & (Tuse_rt < Tnew_E); assign stall_rt_M = (D_A2 != 5'd0) & (check_M ? D_A2 == 5'd31 : D_A2 == M_A3) & (RFWrite_M) & (Tuse_rt < Tnew_M); //更改写入寄存器地址(eg:condition满足向31号写,否则不写) wire M_A3_new = check_M ? (condition ? 5'd31 : 5'd0) : M_A3; //uut W_reg top_w_reg( .M_A3(M_A3_new), ); HCU top_hcu( .M_A3(M_A3_new), ); 3.condition3 condition满足时写入DM中值的低五位 这种情况下可能写入所有的寄存器,直接暂停 1 2 3 4 5 6 7 8 9 10 11 12 13 14 //第三种题型 (eg:condition满足时写入位置为DM的读取值的低五位) assign stall_rs_E = (D_A1 != 5'd0) & (check_E ? 1'b1 : D_A2 == M_A3) & (RFWrite_E) & (Tuse_rs < Tnew_E); assign stall_rs_M = (D_A1 != 5'd0) & (check_M ? 1'b1 : D_A2 == M_A3) & (RFWrite_M) & (Tuse_rs < Tnew_M); assign stall_rt_E = (D_A2 != 5'd0) & (check_E ? 1'b1 : D_A2 == M_A3) & (RFWrite_E) & (Tuse_rt < Tnew_E); assign stall_rt_M = (D_A2 != 5'd0) & (check_M ? 1'b1 : D_A2 == M_A3) & (RFWrite_M) & (Tuse_rt < Tnew_M); //更改写入寄存器地址(eg:写入位置为DM的读取值的低五位) wire M_A3_new = check_M ? DM_out[4:0] : M_A3; //uut W_reg top_w_reg( .M_A3(M_A3_new), ); HCU top_hcu( .M_A3(M_A3_new), );

November 27, 2023 · 3 min · sudo

P5-pipeline-CPU-Design-Document

P5-pipeline-CPU-Design-Document 零.数据通路描述 ​ MIPS架构的五级流水线CPU数据通路有以下五个阶段: 取指阶段F(Fetch):从指令存储器中读取指令 译码阶段D(Decode):从寄存器文件中读取源操作数并对指令译码得到控制信号 执行阶段E(Execute):使用ALU执行计算 存储阶段M(Memory):读或写数据存储 写回阶段(Writeback):将结果写回到寄存器文件 ​ 通过在五个阶段之间加入寄存器来保存前面周期产生的数据(最后一个阶段的寄存器即为GRF),形成五级流水线CPU,数据通路如下图表示: 一.数据命名规范(checkstyle) 在控制信号连线名末尾加上“_阶段字母”,如NPCOp_D,用于区分所属的阶段 在流水线寄存器输出信号前加上“阶段字母_",如:D_A1,用以区分所属阶段 功能部件输出信号前加上功能部件名称 常规MUX命名采用"MUX-部件名-端口名”的命名方式,选择信号命名为"Sel+部件名+端口名" 转发MUX命名采用"HMUX-部件名-端口名"的命名方式,选择信号命名为"Fwd+部件名+端口名" 二.部件设计 1.MCU(main control unit) 1.端口定义列表 ​ 主控制单元模块负责对指令进行译码以及产生控制信号,本CPU的设计采用集中式译码,在P5中需要完成的指令及其需要的控制信号列表如下,其中有些控制信号对应多路选择器的选择。 名称 方向 位宽 描述 D_opcode I 6 D级输出opcode D_funct I 6 D级输出funct SelA3_D I 2 选择当前指令要写入的寄存器,写入E级流水线寄存器 RegWrite_D O 1 GRF写入使能 MemWrite_D O 1 DM写入使能 EXTOp_D O 1 对立即数进行符号扩展还是0扩展 SelEMout_D O 1 选择E,M级转发数据信号 SelWout_D O 2 选择W级转发数据信号 SelALUB_D O 1 ALU的B端口rt数据与32位立即数的选择 CMPOp_D O 3 D级B类指令比较选择 NPCOp_D O 3 写入NPC选择 ALUOp_D O 3 ALU操作信号 DMOp_D O 3 DM操作信号 T_rs_use_D O 2 指令处在D级时还有多少个周期需要使用rs寄存器的值 T_rt_use_D O 2 指令处在D级时还有多少个周期需要使用rt寄存器的值 T_new_D O 2 指令处在D级时还有多少个周期可以产生写入寄存器的新值 2.分指令梳理控制信号 指令 取高电平的控制信号和ALUOp add SelA3_D = 2’b01, RegWrite, ALUOp = 3’b000, NPCOp = 3’b000; sub SelA3_D = 2’b01, RegWrite, ALUOp = 3’b001, NPCOp = 3’b000; ori RegWrite,ALUSrc, SelALUB, ALUOp=3’b010, NPCOp = 3’b000; lui RegWrite,ALUSrc, SelALUB, ALUOp=3’b011, NPCOp = 3’b000; lw RegWrite, SelWout = 2’b01, SelALUB, EXTOp, ALUOp=3’b000, NPCOp = 3’b000; sw MemWrite, SelALUB, EXTOp, ALUOp=3’b000, NPCOp = 3’b000; beq CMPOp = 3’b000,EXTOp, NPCOp = 3’b001, CMPOp = 3’b000; jal RegWrite, SelA3_D = 2’b10, NPCOp = 3’b010; jr NPCOp = 3’b11; nop 相当于sll $0,$0,0,不需要进行特殊处理 3.译码方式的改动 ​ 在P4中,我才用使用reg类型变量记录指令识别的形式,在always块中每次都为代表所有信号的寄存器赋初值0,这样会导致pc一直自增下去,程序不断向后跑(虽然在上机时无影响),在蒋老师的测评机上会出现多输出的情况。在P5中,使用wire类型进行指令的识别,当识别的指令为x时,所有指令对应的wire都是不定值x,导致MCU中输出的控制信号为x,使得pc停下来,可以正常在蒋老师的测评机上跑结果。 ...

November 12, 2023 · 24 min · sudo

支持40条指令P4_Verilog_CPU

P4-Verilog-CPU-Design-Document 零.数据通路描述(P4设计文档中最好加上P3图) ​ 本次设计文档基于P3-logisim-CPU的设计文档完成,P4的主要任务即为将logisim电路映射到verilog代码(看图写话?),对上次P3中实现的每个模块单独建立module.v,利用verilog语言对其行为进行建模,注意本次CPU设计中,不同于P3的异步复位,P4在各模块中使用同步复位!!!,verilog语言表示同步复位与异步复位如下代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 //同步复位表示方法 always@(posedge clk) begin if(reset) begin PC <= 32'h0000_3000; end else begin PC <= npc; end end //异步复位表示方法 将复位信号加入敏感信号列表 always@(posedge clk or posedge reset) begin if(reset) begin PC <= 32'h0000_3000; end else begin PC <= npc; end end 一.模块设计 1.IFU取指令单元 ​ IFU中存储单元有PC寄存器和存储指令的ROM。IFU中存储指令要求的ROM大小为16KiB,即4096*32bit。在verilog语言中使用寄存器数组实现对ROM的模拟,即4096个32位的寄存器。使用系统命令$readmemh("code.txt,ROM")将code.txt中的16进制代码读入名为ROM的数组中,由于PC同步复位到32’h0000_3000,而ROM中对应存储第一条指令的地址为0,即PC寄存器中存储的地址与真实ROM地址存在0x0000_3000差量,故设计reg [31:0] tmp存储实际的地址,即pc-0x0000_3000,进而读出指令的地址为tmp[13:2]。 ...

November 10, 2023 · 11 min · sudo

支持40条指令P3_logisim_CPU

CPU Design Document 1. CPU Design 1.总体设计 ​ 通过对于《计算机组成与设计》一书的阅读,对于P3的CPU设计我有如下思考,设计MIPS架构的CPU的本质在于从指令存储器中读出32位MIPS指令,并对MIPS指令进行解析进而完成指令中要求的操作。在本次实验中,要求实现的指令有add,sub,ori,lw,sw,beq,lui,nop其中,R型指令有add,sub,I型指令有ori,lw,sw,beq,lui,特殊的有nop指令,32位全为0。 RIJ类型指令图: 此次实验中要求实现的基本指令: R型 Operation Op-Code rs rt rd shamt(移位) func add 000000 00000 100000 sub 000000 00000 100010 I型 Operation Op-Code rs rt 16-bit-immediate-value ori 001101 lw 100011 sw 101011 beq 000100 lui 001111 nop ​ 32’b0 ​ 将我们要实现的CPU分为几个模块:IFU(取指令单元),GRF(寄存器堆),ALU(算术逻辑单元),DM(数据存储器),EXT(扩展单元),Controller(控制器)。 ...

November 6, 2023 · 6 min · sudo

OOpre总结

OOpre课程结课总结 ——22373362杜启嵘 ​ 经历九周的OOpre课程的学习,我对面向对象编程有了基本的认识。从类、对象、方法等的基本概念,到最后一次迭代作业涉及到的设计模式,我循序渐进地学习到基本的面向对象编程思想(虽然我的代码仍然不够面向对象QAQ)。 一.代码的最终架构和过程中的重构 ​ 在五次作业的迭代中,我进行了多次代码的重构,前几次作业中的重构我认为是合理的,最后一次作业中的重构是把超过500行的类中的部分方法强行抽离出来放进静态方法类,并把参数分成几行避免行字数超过100字(面向OO-checkstyle的重构)。 1.第一次重构 ​ 在第三次作业中进行了实际上是两次重构,第一次在面临主类中的主方法行数超过60行,对方法中分指令执行的代码抽离出来声明为单独的方法,在编写JUnit时进行了第二次重构,由于第一版代码中解析输入逻辑与代码执行逻辑杂糅,而在编写JUnit时无法对输入进行操作,改为使用课程组提供的利用“二维数组”在统一存储输入内容,在inputhandler类中读取二维数组进行指令解析,这样的架构就能编写满足覆盖率的JUnit,下图为简单的架构图。 二.第二次重构 ​ 第四次作业中新增了战斗日志的概念,我一开始的处理中并没有对fightlog建类,只是在Adventure中建立容器来存储代表战斗日志的字符串,导致处理逻辑比较复杂,结果因为一个方法中的错误逻辑挂了强测,在修改强测的过程中完成了对代码的重构,新增fightlog类,架构图如下 三.第三次重构 ​ 在最后一次迭代开发中,由于类的行数限制,我不得不将一个类拆成两个类,在静态方法类中进行传参,属于是一次很丑陋的重构。 2.使用JUnit的心得体会 ​ 使用JUnit可以在提交测评机之前进行本地测试,可以通过构造数据计算预期结果比对程序输出结果判断程序的正确性,在第六次作业完成过程中涉及到很多计算还有精度的问题,使用JUnit在本地进行测试可以找出一些问题。编写JUnit过程中达到分支覆盖对于验证正确性也有很大帮助,第六次作业中继承关系中覆盖不同子类进行测试帮助我找到了一些bug。在当下阶段使用JUnit的不足在于构造数据过于简单,没有对边界条件进行测试(毕竟手搓复杂数据真的很难绷QWQ),总体来说在几次作业的迭代中,我通过使用JUnit实现了对于程序的本地测试,并且能够发现一些bug,使第一次提交至少通过数据点多了一些。 3.学习OOpre的心得体会 ​ 从面向过程到面向对象的编程思维的转变对于我来说还是有一些难度,我的代码中的很多编写也不够面向对象,导致方法行数爆炸,类行数爆炸,处理逻辑复杂。但是在几次迭代中,我也对面向对象有了基本的认识 理解面向对象的核心概念:面向对象编程是一种基于对象的思维方式。它的核心概念包括类、对象、封装、继承和多态。要想掌握面向对象编程,首先要理解这些概念的含义和关系 不断练习和总结经验:面向对象编程是一种需要不断实践和经验积累的编程方式。通过不断地练习和实践,才能更好地理解和应用面向对象编程的技巧。同时,还要及时总结经验教训,找到自己的不足之处并加以改进 阅读和理解优秀的面向对象代码:课程结束后学习优秀代码 4.对OOpre课程的简单建议 提高中测强度,尽量中测程度的数据过了就不要挂强测(强测挂了真的好压力) 指导书中部分内容可以进行细化,尤其是第七次作业的指导书,对于不同设计模式的解释可以再细致一点(?)

November 4, 2023 · 1 min · sudo