diff options
-rw-r--r-- | hdl/core/reg.py | 47 |
1 files changed, 35 insertions, 12 deletions
diff --git a/hdl/core/reg.py b/hdl/core/reg.py index 130de94..bacf3f1 100644 --- a/hdl/core/reg.py +++ b/hdl/core/reg.py @@ -9,6 +9,25 @@ from hdl.core.alu import ALUFlags @unique +class RegAddr(Enum): + zx = 0 + ax = 1 + bx = 2 + cx = 3 + dx = 4 + ex = 5 + fx = 6 + gx = 7 + hx = 8 + ip = 9 + sp = 10 + flg = 11 + cs0 = 12 + cs1 = 13 + cs2 = 14 + pog = 15 + +@unique class RegFLG(Enum): carry = ALUFlags.carry.value zero = ALUFlags.zero.value @@ -70,7 +89,7 @@ class Reg(Elaboratable): self.cs0 = Signal(32) #13 self.cs1 = Signal(32) #14 self.cs2 = Signal(32) #15 - self.pda = Signal(32) #16 + self.pog = Signal(32) #16 # this is a shortcut for internal testing, use enum RegFLG if using outside of this module setattr(self.flg, 'c', self.flg[RegFLG.carry.value]) @@ -83,13 +102,13 @@ class Reg(Elaboratable): setattr(self.flg, 'halt', self.flg[RegFLG.halt.value]) - reg_list = [self.zx, self.ax, self.bx, self.cx, self.dx, self.ex, self.fx, self.gx, self.hx, self.ip, self.sp, self.flg, self.cs0, self.cs1, self.cs2, self.pda] + reg_list = [self.zx, self.ax, self.bx, self.cx, self.dx, self.ex, self.fx, self.gx, self.hx, self.ip, self.sp, self.flg, self.cs0, self.cs1, self.cs2, self.pog] for idx, reg in enumerate(reg_list): setattr(reg, 'idx', idx) # set idx attribute to each register self.reg_arr = Array(reg_list) - ports_in = [self.wr_en, self.alu_flgs, self.int_sig, self.iret, self.call, self.jump, self.rd_addr, self.stall, self.rd, self.rs1_addr, self.rs2_addr] + ports_in = [self.wr_en, self.stall, self.alu_flgs, self.int_sig, self.iret, self.call, self.jump, self.rd_addr, self.stall, self.rd, self.rs1_addr, self.rs2_addr] ports_out = [self.int_en, self.user_mode, self.rs1, self.rs2, self.ip] self.ports = {'in': ports_in, 'out': ports_out} @@ -108,8 +127,8 @@ class Reg(Elaboratable): with m.If(self.int_sig): m.d.comb += self._inc_ip.eq(0) # do not increment instruction pointer on interrupt - m.d.sync += self.ip.eq(self.rd) # swap ip and cs0 - m.d.sync += self.cs0.eq(self.ip) + m.d.sync += self.ip.eq(self.rd) # get new ip from rd + m.d.sync += self.cs0.eq(self.ip) # save return address in cs0 m.d.sync += self.cs1.eq(self.sp) # swap sp and cs1 m.d.sync += self.sp.eq(self.cs1) @@ -120,19 +139,19 @@ class Reg(Elaboratable): with m.Elif(self.iret & ~self.flg.user_mode): # don't allow iret in user mode, that would be uhhh.... BAD m.d.comb += self._inc_ip.eq(0) - m.d.sync += self.ip.eq(self.cs0) #swap back ip and cs0 - m.d.sync += self.sp.eq(self.cs1) - m.d.sync += self.cs1.eq(self.sp) #swap back sp and cs1 + m.d.sync += self.ip.eq(self.cs0) #copy cs0 to ip + m.d.sync += self.sp.eq(self.cs1) #swap back sp and cs1 + m.d.sync += self.cs1.eq(self.sp) m.d.sync += self.flg.eq(self.cs2) #restore flags from cs2 with m.Elif(self.call): m.d.comb += self._inc_ip.eq(0) - m.d.sync += self.ip.eq(self.rd) + m.d.sync += self.ip.eq(self.cs0) # swap ip and cs0 m.d.sync += self.cs0.eq(self.ip) with m.Elif(self.jump): m.d.comb += self._inc_ip.eq(0) - m.d.sync += self.ip.eq(self.cs0) + m.d.sync += self.ip.eq(self.cs0) # only copy cs0 to ip, do not swap with m.Elif(self.wr_en): with m.Switch(self.rd_addr): @@ -142,9 +161,13 @@ class Reg(Elaboratable): with m.Case(self.ip.idx): #do not directly write to ip register pass - with m.Case(self.pda.idx): # do not write to pda register in user mode + with m.Case(self.cs1.idx): + with m.If(~self.flg.user_mode): + m.d.sync += self.cs1.eq(self.rd) # do not allow writing to system stack pointer in user mode + + with m.Case(self.pog.idx): # do not write to pog register in user mode with m.If(~self.flg.user_mode): - m.d.sync += self.pda.eq(self.rd) + m.d.sync += self.pog.eq(self.rd) with m.Case(self.flg.idx): # mask top half of register to prevent writing to flags in user mode |