summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hdl/core/reg.py47
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