-
Notifications
You must be signed in to change notification settings - Fork 50
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add an initial memory layout (#11)
* Relocate memory script to its own dir * Rename Relocatable to MemoryAddress * Revamped relocatable code * Improve memory segment management * Remove printlns * Rename scripts: relocatable -> memory_value * General fixes and improvements * Change memory address and value logic Changed MemoryAddress offset from felt to uint64, this caused that the current implementation of MemoryValue made no sense, so it was updated as well to include a pointer its two possible data types: - a field element - a memory address * Readability improvements * renamed: memory_segment.go -> memory_manager.go * Add function descriptions * Add felt X felt arithmetic ops for memory values
- Loading branch information
1 parent
366d700
commit b6572d4
Showing
10 changed files
with
585 additions
and
271 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
package memory | ||
|
||
import ( | ||
"fmt" | ||
|
||
f "github.com/consensys/gnark-crypto/ecc/stark-curve/fp" | ||
) | ||
|
||
// Represents a write-once Memory Cell | ||
type Cell struct { | ||
Value *MemoryValue | ||
Accessed bool | ||
} | ||
|
||
type Segment struct { | ||
Data []Cell | ||
} | ||
|
||
func EmptySegment() *Segment { | ||
return &Segment{ | ||
Data: make([]Cell, 0), | ||
} | ||
} | ||
|
||
func EmptySegmentWithCapacity(capacity int) Segment { | ||
return Segment{ | ||
Data: make([]Cell, 0, capacity), | ||
} | ||
} | ||
|
||
func EmptySegmentWithLength(length int) Segment { | ||
return Segment{ | ||
Data: make([]Cell, length), | ||
} | ||
} | ||
|
||
// Writes a new memory value to a specified offset, errors in case of overwriting an existing cell | ||
func (segment *Segment) Write(offset uint64, value *MemoryValue) error { | ||
cell := segment.Data[offset] | ||
if cell.Accessed { | ||
return fmt.Errorf("rewriting cell at %d, old value: %d new value: %d", offset, &cell.Value, &value) | ||
} | ||
cell.Accessed = true | ||
cell.Value = value | ||
return nil | ||
} | ||
|
||
// Reads a memory value from a specified offset at the segment | ||
func (segment *Segment) Read(offset uint64) *MemoryValue { | ||
cell := segment.Data[offset] | ||
cell.Accessed = true | ||
return cell.Value | ||
} | ||
|
||
// todo(rodro): Check out temprary segments | ||
// Represents the whole VM memory divided into segments | ||
type Memory struct { | ||
Segments []*Segment | ||
} | ||
|
||
// todo(rodro): can the amount of segments be known before hand? | ||
func InitializeEmptyMemory() *Memory { | ||
return &Memory{ | ||
// capacity 4 should be enough for the minimum amount of segments | ||
Segments: make([]*Segment, 0, 4), | ||
} | ||
} | ||
|
||
// Allocates a new segment providing its initial data and returns its index | ||
func (memory *Memory) AllocateSegment(data *[]f.Element) (int, error) { | ||
newSegment := EmptySegmentWithLength(len(*data)) | ||
for i := range *data { | ||
memVal := MemoryValueFromFieldElement(&(*data)[i]) | ||
err := newSegment.Write(uint64(i), memVal) | ||
if err != nil { | ||
return 0, fmt.Errorf("cannot allocate new segment: %w", err) | ||
} | ||
} | ||
memory.Segments = append(memory.Segments, &newSegment) | ||
return len(memory.Segments), nil | ||
} | ||
|
||
// Allocates an empty segment and returns its index | ||
func (memory *Memory) AllocateEmptySegment() int { | ||
memory.Segments = append(memory.Segments, EmptySegment()) | ||
return len(memory.Segments) - 1 | ||
} | ||
|
||
// Writes to a memory address a new memory value. Errors if writing to an unallocated | ||
// space or if rewriting a specific cell | ||
func (memory *Memory) Write(address *MemoryAddress, value *MemoryValue) error { | ||
if address.SegmentIndex > uint64(len(memory.Segments)) { | ||
return fmt.Errorf("writing to unallocated segment %d", address.SegmentIndex) | ||
} | ||
|
||
return memory.Segments[address.SegmentIndex].Write(address.Offset, value) | ||
} | ||
|
||
// Reads a memory value from a memory address. Errors if reading from an unallocated | ||
// space. If reading a cell which hasn't been accesed before, it is initalized with | ||
// its default zero value | ||
func (memory *Memory) Read(address *MemoryAddress) (*MemoryValue, error) { | ||
if address.SegmentIndex > uint64(len(memory.Segments)) { | ||
return nil, fmt.Errorf("reading from unallocated segment %d", address.SegmentIndex) | ||
} | ||
|
||
return memory.Segments[address.SegmentIndex].Read(address.Offset), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package memory | ||
|
||
type MemoryManager struct { | ||
Memory *Memory | ||
} | ||
|
||
func CreateMemoryManager() (*MemoryManager, error) { | ||
memory := InitializeEmptyMemory() | ||
|
||
return &MemoryManager{ | ||
Memory: memory, | ||
}, nil | ||
} |
Oops, something went wrong.