受以泪洗面的影响看了一遍Y86 Pipeline的HCL代码+简单注释 很象HDL的行为级描述
####HCL Description of Control for Pipelined Y86 Processor ##
####Coryright (C) Randal E. Bryant, David R. O'Hallaron, 2002 ##
###C Iinclude's. Don't alter these
###C头文件,不要修改
quote 'include <stdio.h>'
quote 'include "isa.h"'
quote 'include "pipeline.h"'
quote 'include "stages.h"'
quote 'include "sim.h"'
quote 'int sim_main(int argc, char *argv[]);'
quote 'int main(int argc, char *argv[]){return sim_main(argc, argv);}'
###Declarations. Do not change/remove/delete any of these
###声明,不要做任何改动
###Symbolic representation of Y86 Instruction Codes
###Y86的指令表示
intsig INOP 'I_NOP' #空操作
intsig IHALT 'I_HALT' #停机
intsig IRRMOVL 'I_RRMOVL' #寄存器-寄存器移动
intsig IIRMOVL 'I_IRMOVL' #立即数-寄存器移动
intsig IRMMOVL 'I_RMMOVL' #寄存器-内存移动
intsig IMRMOVL 'I_MRMOVL' #内存-寄存器移动
intsig IOPL 'I_ALU' #ALU操作
intsig IJXX 'I_JUMP' #跳转
intsig ICALL 'I_CALL' #调用
intsig IRET 'I_RET' #返回
intsig IPUSHL 'I_PUSHL' #入栈
intsig IPOPL 'I_POPL' #出栈
###Symbolic representation of Y86 Registers referenced explicitly
###Y86的寄存器表示
intsig RESP 'REG_ESP' #栈指针寄存器
intsig RNONE 'REG_NONE' #"无寄存器"的保留值
#ALU Functions referenced explicitly
#ALU功能操作表示
intsig ALUADD 'A_ADD' #ALU加法
###Signals that can be referenced by control logic
###被控制逻辑使用的信号
##Pipeline Regsiter F
##F(Fetch 取指阶段)的寄存器流水线
intsig F_predPC 'pc_curr->pc' #PC的预设值
#Intermediate Values in Fetch Stage
#取指阶段的中间表示(IR?)
intsig f_icode 'if_id_next->icode' #取指令的代码
intsig f_ifun 'if_id_next->ifun' #取指令的函数
intsig f_valC 'if_id_next->valc' #被取指令的常数数据(数据表示,比如000表示halt)
intsig f_valP 'if_id_next->valp' #下一条指令的地址
##Pipeline Register D
##D(Decode 解码阶段)的寄存器流水线
intsig D_icode 'if_id_curr->icode' #指令码
intsig D_rA 'if_id_curr->ra' #指令的rA域
intsig D_rB 'if_id_curr->rb' #指令的rB域
intsig D_valP 'if_id_curr->valp' #PC自加,就是下一个指令的地址
#Intermediate Values in Decode Stage
#解码阶段的内部表示
intsig d_srcA 'id_ex_next->srca' #指令解码中的srcA(操作数A)
intsig d_srcB 'id_ex_next->srcb' #指令解码中的srcB
intsig d_rvalA 'd_regvala' #从寄存器中读出的valA(变量A)
intsig d_rvalB 'd_regvalb' #从寄存器中读出的valB
##Pipeline Register E
##E(Execute 执行阶段)的寄存器流水线
intsig E_icode 'id_ex_curr->icode' #指令码
intsig E_ifun 'id_ex_curr->ifun' #指令函数
intsig E_valC 'id_ex_curr->valc' #常量
intsig E_srcA 'id_ex_curr->srca' #源操作数A寄存器ID(放在哪个寄存器中)
intsig E_valA 'id_ex_curr->vala' #操作数A的值
intsig E_srcB 'id_ex_curr->srcb' #源操作数B的寄存器ID
intsig E_valB 'id_ex_curr->valb' #操作数B的值
intsig E_dstE 'id_ex_curr->deste' #目的操作数E的寄存器ID
intsig E_dstM 'id_ex_curr->destm' #目的操作数M的寄存器ID
#Intermediate Values in Execute Stage
#执行阶段的内部表示
intsig e_vslE 'ex_mem_next->vale' #ALU计算出valE
boolsig e_Bch 'ex_mem_next->takebranch' #要分支吗?
##Pipeline Register M
##M(Mem 访存阶段)的寄存器流水线
intsig E_dstM 'ex_mem_curr->icode' #指令码
intsig E_dstM 'ex_mem_curr->ifun' #指令函数
intsig E_dstM 'ex_mem_curr->vala' #源操作数A的值
intsig E_dstM 'ex_mem_curr->deste' #目的操作数D的寄存器ID
intsig E_dstM 'ex_mem_curr->vale' #ALU计算出的E值
intsig E_dstM 'ex_mem_curr->destm' #目的操作数M的寄存器ID
boolsig M_Bch 'ex_mem_curr->takebranch' #分支标志
#Intermediate Values in Memory Stage
#访存阶段的内部表示
intsig m_valM 'mem_wb_next->valme' #valM要写回内存
##Pipeline Register W
##W(Write Back 写回阶段)的寄存器流水线
intsig W_icode 'mem_wb_curr->icode' #指令码
intsig W_dstE 'mem_wb_curr->deste' #目的操作数E的寄存器ID
intsig W_valE 'mem_wb_curr->vale' #ALU计算出的E值
intsig W_dstM 'mem_wb_curr->destm' #目的操作数M的寄存器ID
intsig W_valM 'mem_wb_curr->valm' #内存操作数M的值
###Control Signal Definitions
###控制信号定义
##Fetch Stage
##取指阶段
#What address should instruction be fetched at
#应该从什么地方取指
int f_pc = [
#Mispredicted branch. Fetch at incremented PC
#无预测分支。取值时增加PC。
M_icode == IJXX && !M_Bch : M_valA;
#Completion of RET instruction
#RET返回指令
W_icode == IRET : W_valM;
#Default : Use predicted value of PC
#缺省使用PC的预设值
1 : F_predPC;
];
#Does fetched instruction require a regid byte?
#取得的指令需要寄存器ID吗?
bool need_regids =
f_icode in { IRRMOVL, IOPL, IPUSHL, IPOPL,
IIRMOVL, IRMMOVL, IMRMOVL };
#Does fetched instruction require a constant word?
#取得的指令需要常数吗?
bool need_valC =
f_icode in { IIRMOVL, IRMMOVL, IMRMOVL, IJXX, ICALL };
bool instr_valid = f_icode in
{ INOP, IHALT, IRRMOVL, IIRMOVL, IRMMOVL, IMRMOVL,
IOPL, IJXX, ICALL, IRET, IPUSHL, IPOPL };
#Predict next value of PC
#预取下一个PC值
int new_F_predPC = [
f_icode in { IJXX, ICALL } : f_valC;
1 : f_valP;
];
##Decode Stage
##解码阶段
#What register should be used as the A source?
#哪些寄存器可以被源操作数A使用
int new_E_srcA = [
D_icode in { IRRMOVL, IRMMOVL, IOPL, IPUSHL } : D_rA;
D_icode in { IPOPL, IRET } : RESP;
1 : RNONE; #Don't need register 不需要寄存器
];
#What register should be used as the B source?
#哪些寄存器可以被源操作数B使用
int new_E_srcB = [
D_icode in { IOPL, IRMMOVL, IMRMOVL } : D_rB;
D_icode in { IPUSHL, IPOPL, ICALL, IRET } : RESP;
1 : RNONE; #Don't need register 不需要寄存器
];
#What register should be used as the E destination?
#哪些寄存器可以被目的操作数E使用
int new_E_dstE = [
D_icode in { IRRMOVL, IIRMOVL, IOPL } : D_rB;
D_icode in { IPUSHL, IPOPL, ICALL, IRET } : RESP;
1 : RNONE; #Don't need register 不需要寄存器
];
#What register should be used as the M destination?
#哪些寄存器可以被目的操作数M使用
int new_E_dstM = [
D_icode in { IMRMOVL, IOPL } : D_rA;
1 : RNONE; #Don't need register 不需要寄存器
];
#What should be the A value?
#操作数A的值应该是什么?
#Forward into decode stage for valA
#valA进入decode的下一阶段将会怎样
int new_E_valA = [
D_icode in { ICALL, IJXX } : D_valP; #Use incremented PC 使用增加后的PC
d_srcA == E_dstE : e_valE; #valE将会被exeute阶段使用
d_srcA == M_dstM : m_valM; #valE将会被memory阶段使用
d_srcA == M_dstE : M_valE; #valE将会被memory阶段使用
d_srcA == W_dstM : W_valM; #valE将会被write back阶段使用
d_srcA == W_dstE : W_valE; #valE将会被write back阶段使用
1 : d_rvalA; #使用从寄存器中读出的值
];
int new_E_valB = [
d_srcB == E_dstE : e_valE; #valE将会被exeute阶段使用
d_srcB == M_dstM : m_valM; #valE将会被memory阶段使用
d_srcB == M_dstE : M_valE; #valE将会被memory阶段使用
d_srcB == W_dstM : W_valM; #valE将会被write back阶段使用
d_srcB == W_dstE : W_valE; #valE将会被write back阶段使用
1 : d_rvalB; #使用从寄存器中读出的值
];
##Execute Stage
##执行阶段
#Select input A to ALU
#ALU的输入A
int aluA = [
E_icode in { IRRMOVL, IOPL } : E_valA;
E_icode in { IIRMOVL, IRMMOVL, IMRMOVL } : E_valC;
E_icode in { ICALL, IPUSHL } : -4;
E_icode in { IRET, IPOPL } : 4;
#Other instructions don't need ALU
];
#Select input B to ALU
int aluB = [
E_icode in { IRMMOVL, IMRMOVL, IOPL, ICALL,
IPUSHL, IRET, IPOPL } : E_valB;
E_icode in { IRRMOVL, IIRMOVL } : 0;
#Other instructions don't need ALU
];
#Set the ALU function
#设置ALU功能
int alufun = [
E_icode == IOPL : E_ifun;
1 : ALUADD;
];
##Memory Stage
##访存阶段
#Select memory address
int mem_addr = [
M_icode in { IRMMOVL, IPUSHL, ICALL, IMRMOVL } : M_valE;
M_icode in { IPOPL, IRET } : M_valA;
#Other instructions don't need address
];
#Set read control signal
#设置读控制信号
bool mem_read = M_icode in { IMRMOVL, IPOPL, IRET };
#Set write control signal
bool mem_write = M_icode in { IRMMOVL, IPUSHL, ICALL };
###Pipeline Register Control
###寄存器流水线控制
#Should I stall or inject a bubble into Pipeline Register F?
#我是不是应该在F寄存器流水线中插入'气泡'?
#At most one of these can be true.
#大多数情况下是的。
bool F_bubble = 0;
bool F_stall =
#Condition for a load/use Hazard
#load/use冲突的条件
E_icode in { IMRMOVL, IPOPL } &&
E_dstM in { d_srcA, d_srcB } ||
#Stalling at fetch while ret passes through pipeline
#在ret通过流水线时插入一个取指
IRET in { D_icode, E_icode, M_icode };
#Should I stall or inject a bubble into Pipeline Register D?
#我是不是应该在D寄存器流水线中插入'气泡'?
#At most one of these can be true.
#大多数情况下是的。
bool D_stall =
#Condition for a load/use Hazard
#满足load/use冲突的条件的话
E_icode in { IMRMOVL, IPOPL } &&
E_dstM in { d_srcA, d_srcB };
bool D_bubble =
#Mispredicted branch
#非预测分支
(E_icode == IJXX && !e_Bch) ||
#Stalling at fetch while ret passes through pipeline
#在ret通过流水线时插入一个取指
IRET in { D_icode, E_icode, M_icode };
#Should I stall or inject a bubble into Pipeline Register E?
#我是不是应该在F寄存器流水线中插入'气泡'?
#At most one of these can be true.
#大多数情况下是的。
bool E_stall = 0;
bool E_bubble =
#Mispredicted branch
#非预测分支
(E_icode == IJXX && !e_Bch) ||
#Condition for a load/use Hazard
#满足load/use冲突的条件的话
E_icode in { IMRMOVL, IPOPL } &&
E_dstM in { d_srcA, d_srcB };
#Should I stall or inject a bubble into Pipeline Register M?
#我是不是应该在F寄存器流水线中插入'气泡'?
#At most one of these can be true.
#大多数情况下是的。
bool M_stall = 0;
bool M_bubble =0;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
有流水线的了单周期就没怎么看,设计CPU的话也不知道HCL行不行,还没见过这种硬件设计语言的编译器,也不知道怎么综合。了解的人来说说
我对这种语言也不了解,只是在CS:APP中见过。不知这种语言为何人所创,也不知现在还有没有人使用。只记得按照书中的介绍,貌似有人用它来写模拟器。
我还是继续Verilog吧。感觉HCL设计CPU有点不太靠谱。
c版还想设计软核不?我现在想设计一个类MIPS的,用于教学目的。以后发展到多核和多线程,设计好了再综合到FPGA验证(那些东西没怎么碰过,都不懂 )。
软核设计是一定要设计的,大致的架构我想好了,不可能设计非常复杂的,因为考虑到大家并不是做这个的。另外我觉得此时设计,还不如不设计,因为很多人对verilog和硬件行为并不是非常清楚,硬件和软件之间的差别太大了,拿着软件的思维去设计硬件那么必然会失败。真正的设计,至少等到我先找好工作吧,现在我也不太有心情。准备辞职换工作,但简历还在书写中,想找的公司、工作还没彻底想好。MIPS有个很大的问题,那就是编译器都没做好的类MIPS那不能叫类MIPS。
我对llvm比较熟悉,移植llvm没什么障碍,想到时候移植BSD上去练练手。
对软件和硬件不一样,我只想从逻辑上验证设计是正确的,至于毛刺什么都没想。只是对IPL有个想法,想试试。
没工具,没编译,可能有地方抄错了。
本版的兄弟们谁有Linux下IC设计软件的lisence给我一个吧,什么软件都行。
我下了一个 Xilinx ISE WebPACK,没ID号,没法装,注册的时候发给我的mail有,我给删了。谁有可以用的给我一个,谢谢。
Cadence NC-Sim for linux
够专业
我那个610的lic不行,NC-Verilog一堆错误