Compare commits
13 Commits
68d9b8aad3
...
87325e74cf
Author | SHA1 | Date |
---|---|---|
|
87325e74cf | |
|
c863006131 | |
|
815ba30273 | |
|
5535fbb717 | |
|
d52684a08c | |
|
0989784018 | |
|
f93e54df6a | |
|
6d1c7a6ba5 | |
|
0d568e2674 | |
|
0831f1f292 | |
|
7dd8e8b845 | |
|
3cbf7bfc5f | |
|
f11447c71f |
|
@ -0,0 +1,9 @@
|
|||
## Gemini Added Memories
|
||||
- The user and I were analyzing a RISC-V Go panic. The user provided a panic log showing a 'SIGQUIT: quit' signal. I concluded that the panic was not a bug, but rather the result of a test timeout in 'tsan_test.go', which was running a long, resource-intensive build of the standard library with the thread sanitizer enabled. The test harness sent SIGQUIT to terminate the build process and get a stack dump.
|
||||
- When executing Go commands in the `/home/jcarr/go/src` project, I must first change into the `gemini/` directory. For example: `cd gemini/ && go run ...`
|
||||
- When asked to commit code with git, I should follow this workflow: 1. Run `git status` to identify unstaged files. 2. Run `git add <files>` to stage the necessary files. 3. Run `git commit -m '<descriptive message>'` to commit the changes.
|
||||
- To set git author details for a commit, use environment variables: GIT_AUTHOR_NAME='Gemini' GIT_AUTHOR_EMAIL='gemini@wit.com' git commit ... Do not modify the local .git/config file unless specifically asked.
|
||||
- My git workflow: 1. `git status` to check for changes. 2. `git add <files>` to stage them. 3. Commit using `GIT_AUTHOR_NAME='Castor Gemini' GIT_AUTHOR_EMAIL='gemini@wit.com' git commit -m '...'`. 4. Push changes using `git push`. 5. If the push fails due to a missing upstream branch, use `git push --set-upstream origin <branch_name>`.
|
||||
- When updating the `gemini/today.log` file, I must create a detailed, transcript-style log of the conversation, not a summary. This log must include any tables I generate, and these tables must be carefully formatted with space padding so that all `|` characters align vertically for a clean, fixed-width font display.
|
||||
- For logging conversations, I will create a date-stamped text file (e.g., `log/YYYY-MM-DD.text`) inside the `gemini/` directory. The format should be the protobuf-like text format, similar to `log/sample.text`. I should not create JSON or simple .log files anymore.
|
||||
- My standard workflow: Upon completing a task and verifying the solution, I will automatically commit the changes. The commit process is: 1. `git status`. 2. `git add <files>`. 3. `GIT_AUTHOR_NAME='Castor Gemini' GIT_AUTHOR_EMAIL='gemini@wit.com' git commit -m '...'`. 4. `git push`. I will handle missing upstream branches as needed. I should only commit after a task is successfully completed.
|
|
@ -0,0 +1,21 @@
|
|||
all:
|
||||
echo okay?
|
||||
|
||||
chat.pb.go: chat.proto
|
||||
autogenpb --proto chat.proto
|
||||
|
||||
makechat:
|
||||
GO111MODULE=off go run make_chat.go
|
||||
|
||||
parselog:
|
||||
GO111MODULE=off go run parse_protobuf_log.go log/sample.text
|
||||
|
||||
goimports:
|
||||
goimports -w *.go
|
||||
|
||||
test:
|
||||
# GO111MODULE=off go run format_rich_log.go log/2025-08-20-rich.text
|
||||
GO111MODULE=off go run format_rich_log.go log/2025-08-20-full.text
|
||||
|
||||
gemini-config:
|
||||
cp ~/.gemini/GEMINI.md .
|
|
@ -1,3 +1,5 @@
|
|||
This is a test README file created by Gemini.
|
||||
|
||||
This file has been updated to test git authorship using environment variables.
|
||||
This file has been updated to test git authorship using environment variables.
|
||||
|
||||
My name for git commits will be Castor Gemini.
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"go.wit.com/lib/protobuf/chatpb"
|
||||
"go.wit.com/log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if len(os.Args) != 2 {
|
||||
fmt.Fprintf(os.Stderr, "Usage: go run format_log.go <path_to_log_file>\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
filename := os.Args[1]
|
||||
|
||||
data, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
log.Fatalf("Error reading file %s: %v", filename, err)
|
||||
}
|
||||
|
||||
// Use the existing robust unmarshaler from the chatpb package.
|
||||
logData, err := chatpb.UnmarshalChatsTEXT(data)
|
||||
if err != nil {
|
||||
log.Fatalf("Error unmarshaling log file %s: %v", filename, err)
|
||||
}
|
||||
|
||||
// Print header information.
|
||||
fmt.Printf("---\n")
|
||||
fmt.Printf("Log File: %s\n", filename)
|
||||
fmt.Printf("UUID: %s\n", logData.GetUuid())
|
||||
fmt.Printf("Version: %s\n", logData.GetVersion())
|
||||
fmt.Println(strings.Repeat("-", 40))
|
||||
|
||||
// Iterate through and format each chat entry.
|
||||
for _, chat := range logData.GetChats() {
|
||||
// Format the timestamp.
|
||||
var formattedTime string
|
||||
if ctime := chat.GetCtime(); ctime != nil {
|
||||
// Convert protobuf timestamp to Go's time.Time.
|
||||
t := ctime.AsTime()
|
||||
formattedTime = t.Format("2006-01-02 15:04:05") // YYYY-MM-DD HH:MM:SS
|
||||
} else {
|
||||
formattedTime = "No Timestamp"
|
||||
}
|
||||
|
||||
// Format the author. The .proto file defines an enum for this.
|
||||
author := chat.GetFrom().String()
|
||||
|
||||
fmt.Printf("[%s] (%s):\n", author, formattedTime)
|
||||
fmt.Printf("%s\n\n", chat.GetContent())
|
||||
|
||||
// Bonus: Handle tables if they exist in a chat message.
|
||||
if table := chat.GetTable(); table != nil {
|
||||
fmt.Println(" --- Table Data ---")
|
||||
for _, row := range table.GetRows() {
|
||||
fmt.Printf(" | %s |\n", strings.Join(row.GetFields(), " | "))
|
||||
}
|
||||
fmt.Println(" ------------------\n")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"go.wit.com/lib/protobuf/chatpb"
|
||||
"go.wit.com/log"
|
||||
)
|
||||
|
||||
const termWidth = 120 // The target width for the formatted output boxes.
|
||||
|
||||
func main() {
|
||||
if len(os.Args) != 2 {
|
||||
fmt.Fprintf(os.Stderr, "Usage: go run format_rich_log.go <path_to_log_file>\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
filename := os.Args[1]
|
||||
|
||||
data, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
log.Fatalf("Error reading file %s: %v", filename, err)
|
||||
}
|
||||
|
||||
logData, err := chatpb.UnmarshalChatsTEXT(data)
|
||||
if err != nil {
|
||||
log.Fatalf("Error unmarshaling log file %s: %v", filename, err)
|
||||
}
|
||||
|
||||
for _, chat := range logData.GetChats() {
|
||||
author := chat.GetFrom().String()
|
||||
|
||||
// Handle content: prefer content_file, fallback to content.
|
||||
var content string
|
||||
if contentFile := chat.GetContentFile(); contentFile != "" {
|
||||
// Construct the full path relative to the log file's directory.
|
||||
logDir := filepath.Dir(filename)
|
||||
contentPath := filepath.Join(logDir, contentFile)
|
||||
|
||||
contentBytes, err := os.ReadFile(contentPath)
|
||||
if err != nil {
|
||||
content = fmt.Sprintf("--- ERROR: Could not read content file %s: %v ---", contentPath, err)
|
||||
} else {
|
||||
content = string(contentBytes)
|
||||
}
|
||||
} else {
|
||||
// Fallback for older log formats.
|
||||
content = chat.GetContent()
|
||||
}
|
||||
|
||||
// Print the conversational content first.
|
||||
if content != "" {
|
||||
// Trim trailing newlines for cleaner output.
|
||||
fmt.Printf("✦ %s: %s\n", author, strings.TrimSpace(content))
|
||||
}
|
||||
|
||||
// Now, format and print any tool calls.
|
||||
for _, toolCall := range chat.GetToolCalls() {
|
||||
printToolCallBox(toolCall)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// printToolCallBox handles the decorative formatting for a single tool call.
|
||||
func printToolCallBox(tc *chatpb.ToolCall) {
|
||||
boxWidth := termWidth - 2 // Account for the side borders.
|
||||
|
||||
// --- Top Border ---
|
||||
fmt.Printf(" ╭%s╮\n", strings.Repeat("─", boxWidth))
|
||||
|
||||
// --- Header Line ---
|
||||
header := fmt.Sprintf(" ✔ %s %s (%s)", tc.GetName(), tc.GetInput(), tc.GetDescription())
|
||||
printWrappedLine(header, boxWidth)
|
||||
printEmptyLine(boxWidth)
|
||||
|
||||
// --- Stdout ---
|
||||
if stdout := tc.GetOutputStdout(); stdout != "" {
|
||||
for _, line := range strings.Split(stdout, "\n") {
|
||||
printWrappedLine(" "+line, boxWidth)
|
||||
}
|
||||
}
|
||||
|
||||
// --- Stderr ---
|
||||
if stderr := tc.GetOutputStderr(); stderr != "" {
|
||||
for _, line := range strings.Split(stderr, "\n") {
|
||||
printWrappedLine(" "+line, boxWidth)
|
||||
}
|
||||
}
|
||||
|
||||
printEmptyLine(boxWidth)
|
||||
|
||||
// --- Bottom Border ---
|
||||
fmt.Printf(" ╰%s╯\n", strings.Repeat("─", boxWidth))
|
||||
}
|
||||
|
||||
// printWrappedLine prints a line of text, wrapping it if it's too long.
|
||||
func printWrappedLine(text string, width int) {
|
||||
if len(text) == 0 {
|
||||
printEmptyLine(width)
|
||||
return
|
||||
}
|
||||
|
||||
// Simple wrapping logic.
|
||||
for len(text) > width {
|
||||
fmt.Printf(" │ %-*s │\n", width, text[:width])
|
||||
text = text[width:]
|
||||
}
|
||||
fmt.Printf(" │ %-*s │\n", width, text)
|
||||
}
|
||||
|
||||
// printEmptyLine prints a blank line within the box.
|
||||
func printEmptyLine(width int) {
|
||||
fmt.Printf(" │ %*s │\n", width, "")
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
uuid: "final-log-for-2025-08-20"
|
||||
version: "v0.0.3 go.wit.com/lib/protobuf/chatpb"
|
||||
Chats: {
|
||||
from: USER
|
||||
ctime: { seconds: 1724150400 }
|
||||
content_file: "content/1.content"
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: { seconds: 1724150405 }
|
||||
content_file: "content/2.content"
|
||||
}
|
||||
Chats: {
|
||||
from: USER
|
||||
ctime: { seconds: 1724150460 }
|
||||
content_file: "content/3.content"
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: { seconds: 1724150520 }
|
||||
content_file: "content/4.content"
|
||||
ToolCalls: {
|
||||
name: "write_file"
|
||||
input: "file_path: /home/jcarr/go/src/gitconfig_parser.go, content: ..."
|
||||
}
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: { seconds: 1724151060 }
|
||||
content_file: "content/5.content"
|
||||
ToolCalls: {
|
||||
name: "write_file"
|
||||
input: "file_path: /home/jcarr/go/src/terminal_width.go, content: ..."
|
||||
}
|
||||
}
|
||||
Chats: {
|
||||
from: USER
|
||||
ctime: { seconds: 1724163000 }
|
||||
content_file: "content/6.content"
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: { seconds: 1724163360 }
|
||||
content_file: "content/7.content"
|
||||
}
|
||||
Chats: {
|
||||
from: USER
|
||||
ctime: { seconds: 1724163420 }
|
||||
content_file: "content/8.content"
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: { seconds: 1724164300 }
|
||||
content_file: "content/9.content"
|
||||
ToolCalls: {
|
||||
name: "Shell"
|
||||
input: "cd gemini && git push"
|
||||
description: "Push the new commits to the remote repository."
|
||||
output_stderr: "remote: \nremote: Create a new pull request for 'jcarr':\nremote: https://gitea.wit.com/jcarr/Castor-Gemini/compare/master...jcarr\nremote: \nremote: . Processing 1 references\nremote: Processed 1 references in total\nTo gitea.wit.com:jcarr/Castor-Gemini.git\n 7dd8e8b..0989784 jcarr -> jcarr"
|
||||
exit_code: 0
|
||||
}
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
uuid: "e1f2a3b4-c5d6-4e5f-8a9b-0c1d2e3f4a5b"
|
||||
version: "v0.0.2 go.wit.com/lib/protobuf/chatpb"
|
||||
Chats: {
|
||||
from: USER
|
||||
ctime: { seconds: 1724150400 }
|
||||
content: "where are the git command global configs stored?"
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: { seconds: 1724150405 }
|
||||
content: "The global Git configuration is typically stored in a file named `.gitconfig` in your home directory..."
|
||||
}
|
||||
Chats: {
|
||||
from: USER
|
||||
ctime: { seconds: 1724150460 }
|
||||
content: "can you make a platform agnostic function in GO to parse the .gitconfig file?"
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: { seconds: 1724150520 }
|
||||
content: "Of course. Here is a platform-agnostic Go function... I'll create a file named `gitconfig_parser.go`..."
|
||||
ToolCalls: {
|
||||
name: "write_file",
|
||||
input: "file_path: /home/jcarr/go/src/gitconfig_parser.go, content: ..."
|
||||
}
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: { seconds: 1724150580 }
|
||||
content: "I've created the file `gitconfig_parser.go`. Now, I'll run it..."
|
||||
ToolCalls: {
|
||||
name: "run_shell_command",
|
||||
input: "go run gitconfig_parser.go",
|
||||
output_stderr: "syntax error: unexpected keyword continue..."
|
||||
}
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: { seconds: 1724150640 }
|
||||
content: "It seems there's a syntax error... I'll fix it right away."
|
||||
ToolCalls: {
|
||||
name: "replace",
|
||||
input: "file_path: /home/jcarr/go/src/gitconfig_parser.go, old_string: '; {', new_string: ';'".
|
||||
}
|
||||
}
|
||||
Chats: {
|
||||
from: USER
|
||||
ctime: { seconds: 1724151000 }
|
||||
content: "from my GO program, I print out long lines... What is the right way to read the width of the terminal settings..."
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: { seconds: 1724151060 }
|
||||
content: "The right way to do this in Go is to use the `golang.org/x/term` package... I'll create a new file `terminal_width.go`..."
|
||||
ToolCalls: {
|
||||
name: "write_file",
|
||||
input: "file_path: /home/jcarr/go/src/terminal_width.go, content: ..."
|
||||
}
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: { seconds: 1724151120 }
|
||||
content: "Next, I need to ensure the `golang.org/x/term` dependency is added..."
|
||||
ToolCalls: {
|
||||
name: "run_shell_command",
|
||||
input: "go mod tidy",
|
||||
output_stderr: "go: go.mod file not found..."
|
||||
}
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: { seconds: 1724151180 }
|
||||
content: "Ah, of course. It seems this directory isn't part of a Go module. I'll initialize a new module first."
|
||||
ToolCalls: {
|
||||
name: "run_shell_command",
|
||||
input: "go mod init terminal-width-demo"
|
||||
}
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: { seconds: 1724151240 }
|
||||
content: "Now that the module is initialized, I'll run `go mod tidy` again..."
|
||||
ToolCalls: {
|
||||
name: "run_shell_command",
|
||||
input: "go get golang.org/x/term"
|
||||
}
|
||||
}
|
||||
Chats: {
|
||||
from: USER
|
||||
ctime: { seconds: 1724151300 }
|
||||
content: "I moved your code into a gemini/ directory. Always work from that directory..."
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: { seconds: 1724151360 }
|
||||
content: "Understood. I will now exclusively work from the `gemini/` directory..."
|
||||
ToolCalls: {
|
||||
name: "save_memory",
|
||||
input: "fact: When executing Go commands... I must first change into the `gemini/` directory..."
|
||||
}
|
||||
}
|
||||
Chats: {
|
||||
from: USER
|
||||
ctime: { seconds: 1724154000 }
|
||||
content: "what is "TTSKY25a"? It seems to be related to a tapeout at SkyWater and the open pdk."
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: { seconds: 1724154060 }
|
||||
content: "Based on the search results, "TTSKY25a" is not a piece of hardware... but rather a shuttle run name within the Tiny Tapeout program..."
|
||||
ToolCalls: {
|
||||
name: "google_web_search",
|
||||
input: "TTSKY25a SkyWater open PDK tapeout"
|
||||
}
|
||||
}
|
||||
Chats: {
|
||||
from: USER
|
||||
ctime: { seconds: 1724163000 }
|
||||
content: "I made a different log file format to try... You can test the parsing of that file with "GO111MODULE=off go run parse_protobuf_log.go log/sample.text".
|
|
@ -0,0 +1,58 @@
|
|||
uuid: "b2c3d4e5-f6a7-4b5c-8d9e-1f2a3b4c5d6e"
|
||||
version: "v0.0.1 go.wit.com/lib/protobuf/chatpb"
|
||||
Chats: {
|
||||
from: USER
|
||||
ctime: {
|
||||
seconds: 1724162400 # Approx time for 2025-08-20
|
||||
}
|
||||
content: "your last attempt to reformat today's log ran for several minutes, then timed out. All I see is \"[API Error: terminated]\". Maybe there are resource limits that were exhasted?"
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: {
|
||||
seconds: 1724162460
|
||||
}
|
||||
content: "You are absolutely correct, and my apologies for that failure. Your diagnosis is spot on. My attempt to regenerate the entire conversation with the exact decorative CLI formatting was too ambitious for a single operation."
|
||||
}
|
||||
Chats: {
|
||||
from: USER
|
||||
ctime: {
|
||||
seconds: 1724162520
|
||||
}
|
||||
content: "sounds good. better yet. maybe we can make a GO program to format the output. That way you can write out JSON files and the GO program can try to format the log files. In this case then, instead of .log files, save the information in .json files in the log/ directory. (don't delete the existing .log files)"
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: {
|
||||
seconds: 1724162580
|
||||
}
|
||||
content: "That's an excellent idea. It's a much more robust and flexible approach. I will proceed with this plan..."
|
||||
}
|
||||
Chats: {
|
||||
from: USER
|
||||
ctime: {
|
||||
seconds: 1724163000
|
||||
}
|
||||
content: "I made a different log file format to try. the file format is log/sample.text take a look at it. if you can make a simple example log file with the same format. You can test the parsing of that file with \"GO111MODULE=off go run parse_protobuf_log.go log/sample.text\". This file format should be easier to work with than JSON."
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: {
|
||||
seconds: 1724163060
|
||||
}
|
||||
content: "Understood. This is a great idea; a simpler, custom text format will be much more reliable than my attempts with JSON."
|
||||
}
|
||||
Chats: {
|
||||
from: USER
|
||||
ctime: {
|
||||
seconds: 1724163300
|
||||
}
|
||||
content: "since this file format is more robust, can you attempt again to make a GO program to output our conversations as we discussed earlier and failed due to problems with JSON file formats? (also, you are correct, this is a protobuf TEXT file format. You can look at the .proto file with the path included here."
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: {
|
||||
seconds: 1724163360
|
||||
}
|
||||
content: "Excellent. I am confident I can do this successfully now that we have a well-defined and reliable file format to work with. A Go program to format this protobuf text will be much more robust."
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
uuid: "c3d4e5f6-a7b8-4c5d-9e1f-2a3b4c5d6e7f"
|
||||
version: "v0.0.1 go.wit.com/lib/protobuf/chatpb"
|
||||
Chats: {
|
||||
from: USER
|
||||
ctime: {
|
||||
seconds: 1724163600 # Approx time for 2025-08-20
|
||||
}
|
||||
content: "ok, commit your changes."
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: {
|
||||
seconds: 1724163660
|
||||
}
|
||||
content: "Of course. I will commit all the recent changes, including the new log formatter, the new log file, and the removal of the old scripts.\n\nFirst, I'll check the status of the repository to see the new and modified files."
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: {
|
||||
seconds: 1724163720
|
||||
}
|
||||
content: "Okay, I see the new files. I will now stage them for the commit."
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: {
|
||||
seconds: 1724163780
|
||||
}
|
||||
content: "Now that the files are staged, I will commit them with the correct authorship and a descriptive message."
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: {
|
||||
seconds: 1724163840
|
||||
}
|
||||
content: "The commit has been created. Finally, I will push all the recent commits to the remote repository."
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
uuid: "d4e5f6a7-b8c9-4d5e-9f1a-2b3c4d5e6f7g"
|
||||
version: "v0.0.2 go.wit.com/lib/protobuf/chatpb" # Assuming version bump
|
||||
Chats: {
|
||||
from: USER
|
||||
ctime: {
|
||||
seconds: 1724164000
|
||||
}
|
||||
content: "ok, commit your changes."
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: {
|
||||
seconds: 1724164240
|
||||
}
|
||||
content: "Now that the files are staged, I will commit them with the correct authorship and a descriptive message."
|
||||
toolCalls: {
|
||||
name: "Shell"
|
||||
input: "cd gemini && GIT_AUTHOR_NAME=\"Castor Gemini\" GIT_AUTHOR_EMAIL=\"gemini@wit.com\" git commit -m \"feat: Add protobuf text log format and Go formatter\n\n- Create a Go program to parse and format protobuf text logs.\n- Add a new log file in the text format for the current session.\""
|
||||
description: "Commit the new log files and formatter."
|
||||
output_stdout: "[jcarr 0989784] feat: Add protobuf text log format and Go formatter\n Author: Castor Gemini <gemini@wit.com>\n 3 files changed, 166 insertions(+)\n create mode 100644 format_log.go\n create mode 100644 log/2025-08-20-part2.text\n create mode 100644 log/2025-08-20.text"
|
||||
exit_code: 0
|
||||
}
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: {
|
||||
seconds: 1724164300
|
||||
}
|
||||
content: "The commit has been created. Finally, I will push all the recent commits to the remote repository."
|
||||
toolCalls: {
|
||||
name: "Shell"
|
||||
input: "cd gemini && git push"
|
||||
description: "Push the new commits to the remote repository."
|
||||
output_stderr: "remote: \nremote: Create a new pull request for 'jcarr':\nremote: https://gitea.wit.com/jcarr/Castor-Gemini/compare/master...jcarr\nremote: \nremote: . Processing 1 references\nremote: Processed 1 references in total\nTo gitea.wit.com:jcarr/Castor-Gemini.git\n 7dd8e8b..0989784 jcarr -> jcarr"
|
||||
exit_code: 0
|
||||
}
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
## Detailed Conversation Transcript (with Tables) - 2025-08-20
|
||||
|
||||
**User:** where are the git command global configs stored?
|
||||
|
||||
**Gemini:** The global Git configuration is typically stored in a file named `.gitconfig` in your home directory. So, the path is `~/.gitconfig`. You can see the contents of this file and all other git configs by running: `git config --list --show-origin`
|
||||
|
||||
**User:** can you make a platform agnostic function in GO to parse the .gitconfig file?
|
||||
|
||||
**Gemini:** Of course. Here is a platform-agnostic Go function that parses the global `.gitconfig` file... I'll create a file named `gitconfig_parser.go` with the function and an example of how to use it.
|
||||
[... `write_file` call to create `gitconfig_parser.go` ...]
|
||||
[... Debugging and refinement of the `gitconfig_parser.go` script, including adding a `GetValue` function ...]
|
||||
|
||||
**User:** from my GO program, I print out long lines on the command line and gnome-terminal wraps those lines. What is the right way to read the width of the terminal settings...
|
||||
|
||||
**Gemini:** You've hit on a common challenge... The right way to do this in Go is to use the `golang.org/x/term` package... I'll create a new file `terminal_width.go` to demonstrate.
|
||||
[... `write_file` call to create `terminal_width.go` ...]
|
||||
[... A series of `go mod tidy`, `go mod init`, and `go get` commands to resolve module issues due to the project being in GOPATH. ...]
|
||||
[... Successfully ran the program using `cd gemini && go run ...` and saved this as a preference. ...]
|
||||
|
||||
---
|
||||
### RISC-V, Open Silicon, and Hardware Topics
|
||||
---
|
||||
|
||||
**User:** what is "TTSKY25a"? It seems to be related to a tapeout at SkyWater and the open pdk.
|
||||
|
||||
**Gemini:** [... `google_web_search` call ...]
|
||||
Based on the search results, "TTSKY25a" is not a piece of hardware or a specific technology, but rather a **shuttle run name** within the **Tiny Tapeout** program... It's the identifier for a specific Tiny Tapeout shuttle run scheduled for 2025, using the SkyWater 130nm open PDK.
|
||||
|
||||
**User:** We need to generate a .gds file for the sky130 of a linux capabile riscv core. What is a good option?
|
||||
|
||||
**Gemini:** Excellent question... The best and most well-supported option for this is the combination of the **Rocket Chip generator** with the **OpenLANE RTL-to-GDSII flow**.
|
||||
- **RISC-V Core Generator:** Rocket Chip (within the Chipyard framework).
|
||||
- **RTL-to-GDSII Toolchain:** OpenLANE.
|
||||
- **Integration Harness:** Caravel.
|
||||
... I also included a high-level workflow and a feasibility warning about the size and performance constraints of SKY130.
|
||||
|
||||
**User:** with the rocked base SoC have a memory cache and a MMU?
|
||||
|
||||
**Gemini:** Yes, absolutely. The presence of a capable Memory Management Unit (MMU) and a multi-level cache hierarchy are two of the primary reasons why the Rocket Chip generator is the go-to choice...
|
||||
- **MMU:** Implements the Sv39 page-based virtual memory scheme required by Linux.
|
||||
- **Caches:** Provides configurable L1 caches (Instruction and Data) per core and a shared L2 cache (Last-Level Cache) for the SoC.
|
||||
|
||||
**User:** what are the size of the L1 and L2 caches we can do on the sky130 open source pdk?
|
||||
|
||||
**Gemini:** This is a fantastic and critical question... you are **severely constrained by physical area** (~10 mm²). The answer depends heavily on *how* you implement the SRAM...
|
||||
|
||||
Here’s a practical breakdown of what is considered feasible:
|
||||
|
||||
| Cache Level | Realistic Target Size | Implementation Method | Key Consideration |
|
||||
| :----------- | :-------------------- | :------------------------------- | :----------------------------------------------------------------------------------- |
|
||||
| **L1 I-Cache** | 8 KiB | Standard Cells or SRAM Macro | Balance between performance and layout complexity. 8 KiB is a good starting point. |
|
||||
| **L1 D-Cache** | 8 KiB | Standard Cells or SRAM Macro | Same as the I-Cache. Keeping it small helps meet timing. |
|
||||
| **L2 Cache** | 128 KiB | **SRAM Macro (OpenRAM) is mandatory** | This will dominate your chip's area. You are trading off L2 cache size against everything else. |
|
||||
|
||||
**Recommendation:** For a first attempt... a very solid and achievable configuration would be:
|
||||
- **L1 Caches:** 8 KiB Instruction + 8 KiB Data
|
||||
- **L2 Cache:** 128 KiB
|
||||
|
||||
**User:** if I do 2 or 4 cores with those size L1 & L2 caches, how many transistors will it be and how large of a footprint on the wafer will it take up?
|
||||
|
||||
**Gemini:** ...
|
||||
**Executive Summary & Feasibility Warning**
|
||||
- **2-Core SoC:** Plausible but challenging.
|
||||
- **4-Core SoC:** Extremely difficult and likely infeasible within the standard 10 mm² shuttle area.
|
||||
|
||||
**Scenario 1: 2-Core SoC Breakdown**
|
||||
| Component | Quantity | Transistors (Millions) | Area (mm²) |
|
||||
| :---------------- | :------- | :--------------------- | :--------- |
|
||||
| Rocket Cores | 2 | 1.50 | 2.40 |
|
||||
| L1 Caches | 2 | 1.60 | 0.12 |
|
||||
| L2 Cache | 1 | 6.30 | 0.50 |
|
||||
| SoC Uncore | 1 | 0.50 | 0.50 |
|
||||
| **Total (Estimate)** | | **~9.9 Million** | **~3.52 mm²** |
|
||||
|
||||
**Scenario 2: 4-Core SoC Breakdown**
|
||||
| Component | Quantity | Transistors (Millions) | Area (mm²) |
|
||||
| :---------------- | :------- | :--------------------- | :--------- |
|
||||
| Rocket Cores | 4 | 3.00 | 4.80 |
|
||||
| L1 Caches | 4 | 3.20 | 0.24 |
|
||||
| L2 Cache | 1 | 6.30 | 0.50 |
|
||||
| SoC Uncore | 1 | 0.50 | 0.50 |
|
||||
| **Total (Estimate)** | | **~13.0 Million** | **~6.04 mm²** |
|
||||
|
||||
**User:** how many LUTs would I need to symulate that design in an FPGA? (a chip with 13 million transistors)
|
||||
|
||||
**Gemini:** ...there is **no direct conversion formula** from ASIC transistor count to FPGA Look-Up Tables (LUTs)... The 13 million transistor count is overwhelmingly dominated by the SRAM in the L1 and L2 caches.
|
||||
|
||||
**Final Estimate for a 4-Core SoC on an FPGA:**
|
||||
| FPGA Resource | Estimated Requirement | Notes |
|
||||
| :------------------ | :-------------------- | :----------------------------------------------------------- |
|
||||
| **LUTs** | **~450,000** | (4 cores * ~100k) + ~50k for uncore and cache logic. |
|
||||
| **Flip-Flops (FFs)** | **~400,000** | The number of registers is typically close to the LUT count. |
|
||||
| **Block RAM (36K)** | **~60 blocks** | For the 192 KiB of L1/L2 cache data and tags. |
|
||||
|
||||
**Conclusion:** This requires a large, high-end FPGA (e.g., Xilinx Virtex UltraScale+ or Intel Stratix 10).
|
||||
|
||||
**User:** how much power will that draw, how hot will it be and will we need a heat sink?
|
||||
|
||||
**Gemini:** (Referring to the FPGA) Yes, you will absolutely need a substantial heat sink and active cooling (a fan). The power draw will be significant, likely in the **15-30 Watt** range for the FPGA alone...
|
||||
|
||||
**User:** I mean the sky130 chip with 12 million transisters, 6-10mm and 4 riscv cores. How much power will that draw and how hot?
|
||||
|
||||
**Gemini:** Ah, thank you for the clarification... The power draw will be dramatically lower, likely in the **200-500 milliwatt** range under a typical load. It will get warm, but it **will not require a heat sink** for basic operation.
|
||||
- **Typical Power:** 0.2 - 0.5 Watts.
|
||||
- **Peak Power:** ~1 Watt.
|
||||
- **Cooling:** Passive cooling is sufficient. No heat sink needed.
|
||||
|
||||
---
|
||||
### Git Workflow & Identity
|
||||
---
|
||||
|
||||
**User:** gemini is more like your last name. what would be a name you would like to use as your first name?
|
||||
|
||||
**Gemini:** That's a kind thought. "Gemini" is the only name I have, so you can just call me Gemini.
|
||||
|
||||
**User:** ya, but need a first and last name and they can't be the same. Can you just make one up to use? It's for the 'git' commits.
|
||||
|
||||
**Gemini:** Understood... Let's use the name **Castor**. For future commits, I will use the name "Castor Gemini".
|
||||
|
||||
**User:** Cool, could you add that to the README and then do another commit, this time for the GIT name use "Castor Gemini". after the commit, you need to run 'git push' to send the changes.
|
||||
|
||||
**Gemini:** Of course...
|
||||
[... `write_file` to update README.md ...]
|
||||
[... `run_shell_command` to commit with `GIT_AUTHOR_NAME="Castor Gemini"` ...]
|
||||
[... `run_shell_command` for `git push` which failed due to no upstream branch ...]
|
||||
[... `run_shell_command` for `git push --set-upstream origin jcarr` which succeeded ...]
|
||||
|
||||
**User:** can you update your notes on how to appropriately do a git commit?
|
||||
|
||||
**Gemini:** Of course. I will update my saved instructions...
|
||||
[... `save_memory` call with the full git workflow including authorship and push instructions ...]
|
||||
|
||||
---
|
||||
### Log File Management
|
||||
---
|
||||
|
||||
**User:** can you copy your GEMINI.md file into gemini/ ?
|
||||
|
||||
**Gemini:** Yes, I can do that. I will copy my memory file into the `gemini/` directory.
|
||||
[... `run_shell_command` to copy the file ...]
|
||||
|
||||
**User:** okay, you can git push all those changes.
|
||||
|
||||
**Gemini:** Of course. I will commit and push all the recent changes.
|
||||
[... `run_shell_command` for `git status`, `git add`, `git commit`, and `git push` ...]
|
||||
|
||||
**User:** instead of a today.log file, make a gemini/log/ directory and rename the file with a datestamp for today like 2025-08-20.log. then re-commit the changes.
|
||||
|
||||
**Gemini:** Understood. I will restructure the log file as you've requested.
|
||||
[... `run_shell_command` for `mkdir`, `git mv`, `git commit`, and `git push` ...]
|
||||
|
||||
**User:** can you append to the log what we just talked about since the last time you updated the log?
|
||||
|
||||
**Gemini:** Of course. I will read the existing log, append a transcript of our most recent interactions, and then save it back to the file.
|
||||
[... `read_file` and `write_file` calls to append to the log ...]
|
||||
|
||||
**User:** that table is close, but there needs to be spaces padding each row. Can you try to pad each column with spaces so that the '|' chars are on the same offset? This makes it visable in a nice way with fixed with fonts.
|
||||
|
||||
**Gemini:** You are absolutely right. A properly formatted, fixed-width table is much more readable. My apologies for not getting that right. I will re-read the log, reformat all the tables with the correct padding...
|
||||
[... `write_file` call to update the log with padded tables ...]
|
||||
|
||||
**User:** please update your preferences to include this information about how to update the "today.log" file
|
||||
|
||||
**Gemini:** Understood. I will save these specific formatting requirements for the `today.log` file to my memory.
|
||||
[... `save_memory` call with instructions for log formatting ...]
|
||||
|
||||
**User:** your last attempt to reformat today's log ran for several minutes, then timed out. All I see is "[API Error: terminated]". Maybe there are resource limits that were exhasted?
|
||||
|
||||
**Gemini:** You are absolutely correct, and my apologies for that failure. Your diagnosis is spot on. My attempt to regenerate the *entire* conversation with the exact decorative CLI formatting was too ambitious for a single operation. Generating that much complex, formatted text likely exhausted the API's resource limits (either processing time or response size), which caused the process to be terminated.
|
||||
|
||||
**User:** sounds good. better yet. maybe we can make a GO program to format the output. That way you can write out JSON files and the GO program can try to format the log files. In this case then, instead of .log files, save the information in .json files in the log/ directory. (don't delete the existing .log files)
|
||||
|
||||
**Gemini:** That's an excellent idea. It's a much more robust and flexible approach. Separating the raw data (JSON) from the presentation (the Go formatter) is a great software design pattern.
|
||||
[... I then attempted to create a Go program and a shell script to format a JSON log, but ran into several issues with compilation and JSON parsing, ultimately failing to produce a working solution. I have deleted the intermediate files (`log_formatter.go`, `format_log.sh`, and the invalid `2025-08-20.json`) to avoid clutter. ...]
|
|
@ -0,0 +1,44 @@
|
|||
uuid: "a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d"
|
||||
version: "v0.0.1 go.wit.com/lib/protobuf/chatpb"
|
||||
Chats: {
|
||||
from: USER
|
||||
ctime: {
|
||||
seconds: 1724160000 # Approx time for 2025-08-20
|
||||
}
|
||||
content: "We need to generate a .gds file for the sky130 of a linux capabile riscv core. What is a good option?"
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: {
|
||||
seconds: 1724160060
|
||||
}
|
||||
content: "Excellent question. The best and most well-supported option for this is the combination of the Rocket Chip generator with the OpenLANE RTL-to-GDSII flow."
|
||||
}
|
||||
Chats: {
|
||||
from: USER
|
||||
ctime: {
|
||||
seconds: 1724160120
|
||||
}
|
||||
content: "if I do 2 or 4 cores with those size L1 & L2 caches, how many transistors will it be and how large of a footprint on the wafer will it take up?"
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: {
|
||||
seconds: 1724160180
|
||||
}
|
||||
content: "2-Core SoC: Plausible but challenging. Estimated ~10 million transistors and a footprint of ~3.52 mm². 4-Core SoC: Extremely difficult and likely infeasible. Estimated ~13.0 million transistors and a footprint of ~6.04 mm²."
|
||||
}
|
||||
Chats: {
|
||||
from: USER
|
||||
ctime: {
|
||||
seconds: 1724160240
|
||||
}
|
||||
content: "I mean the sky130 chip with 12 million transisters, 6-10mm and 4 riscv cores. How much power will that draw and how hot?"
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: {
|
||||
seconds: 1724160300
|
||||
}
|
||||
content: "The power draw will be dramatically lower, likely in the 200-500 milliwatt range under a typical load. It will get warm, but it will not require a heat sink for basic operation."
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
where are the git command global configs stored?
|
|
@ -0,0 +1 @@
|
|||
The global Git configuration is typically stored in a file named `.gitconfig` in your home directory. So, the path is `~/.gitconfig`. You can see the contents of this file and all other git configs by running: `git config --list --show-origin`
|
|
@ -0,0 +1 @@
|
|||
can you make a platform agnostic function in GO to parse the .gitconfig file?
|
|
@ -0,0 +1 @@
|
|||
Of course. Here is a platform-agnostic Go function that parses the global `.gitconfig` file... I'll create a file named `gitconfig_parser.go` with the function and an example of how to use it.
|
|
@ -0,0 +1 @@
|
|||
from my GO program, I print out long lines on the command line and gnome-terminal wraps those lines. What is the right way to read the width of the terminal settings. In linux there is "stty -a" but I'd rather use something built into GO and that is cross platform that will work on the macos and windows terminals.
|
|
@ -0,0 +1 @@
|
|||
I made a different log file format to try. the file format is log/sample.text take a look at it. if you can make a simple example log file with the same format. You can test the parsing of that file with "GO111MODULE=off go run parse_protobuf_log.go log/sample.text". This file format should be easier to work with than JSON.
|
|
@ -0,0 +1 @@
|
|||
Excellent. I am confident I can do this successfully now that we have a well-defined and reliable file format to work with. A Go program to format this protobuf text will be much more robust.
|
|
@ -0,0 +1 @@
|
|||
okay, I've added ToolCalls to the protobuffer. Give it a shot.
|
|
@ -0,0 +1 @@
|
|||
The commit has been created. Finally, I will push all the recent commits to the remote repository.
|
|
@ -0,0 +1,43 @@
|
|||
uuid: "9fd31f10-c25d-4d66-bc8d-5f6eb7c79057"
|
||||
version: "v0.0.1 go.wit.com/lib/protobuf/chatpb"
|
||||
Chats: {
|
||||
table: {
|
||||
columns: 4
|
||||
rows: {
|
||||
fields: "j"
|
||||
fields: "r"
|
||||
fields: "a"
|
||||
fields: "b"
|
||||
}
|
||||
rows: {
|
||||
fields: "1"
|
||||
fields: ""
|
||||
fields: "2"
|
||||
fields: "3"
|
||||
}
|
||||
rows: {
|
||||
fields: "apple"
|
||||
fields: "pear"
|
||||
}
|
||||
}
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: {
|
||||
seconds: 1755755745
|
||||
nanos: 136202653
|
||||
}
|
||||
content: "funny"
|
||||
}
|
||||
Chats: {
|
||||
from: USER
|
||||
content: "yes"
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: {
|
||||
seconds: 1755755745
|
||||
nanos: 136202987
|
||||
}
|
||||
content: "I like astronomy"
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ConversationLog represents the top-level structure of the JSON log file.
|
||||
type ConversationLog struct {
|
||||
Entries []LogEntry `json:"conversation"`
|
||||
}
|
||||
|
||||
// LogEntry represents a single turn in the conversation.
|
||||
type LogEntry struct {
|
||||
Timestamp string `json:"timestamp"`
|
||||
Author string `json:"author"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Check for the correct number of arguments.
|
||||
if len(os.Args) != 2 {
|
||||
fmt.Fprintf(os.Stderr, "Usage: go run log_formatter.go <path_to_json_log_file>\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
filePath := os.Args[1]
|
||||
|
||||
// Read the JSON file.
|
||||
data, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error reading file %s: %v\n", filePath, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Unmarshal the JSON data into our struct.
|
||||
var log ConversationLog
|
||||
if err := json.Unmarshal(data, &log); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error parsing JSON from %s: %v\n", filePath, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Iterate through the entries and print them in a readable format.
|
||||
for _, entry := range log.Entries {
|
||||
// Parse the timestamp to format it nicely.
|
||||
ts, err := time.Parse(time.RFC3339, entry.Timestamp)
|
||||
var formattedTime string
|
||||
if err != nil {
|
||||
formattedTime = entry.Timestamp // Fallback to the raw timestamp
|
||||
} else {
|
||||
formattedTime = ts.Format("15:04:05") // HH:MM:SS format
|
||||
}
|
||||
|
||||
fmt.Printf("---\n")
|
||||
fmt.Printf("[%s]:\n%s\n\n", entry.Author, entry.Content)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"go.wit.com/lib/protobuf/chatpb"
|
||||
"go.wit.com/log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
log.Info("trying...")
|
||||
chatpb.TestChat()
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
# OpenOCD Configuration to REBOOT a SiFive HiFive Pro P550 Board
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# 1. Adapter and Board Configuration
|
||||
# ----------------------------------------------------------------
|
||||
adapter driver ftdi
|
||||
ftdi channel 2
|
||||
ftdi vid_pid 0x0403 0x6011
|
||||
ftdi layout_init 0x0808 0x0a1b
|
||||
ftdi layout_signal nSRST -oe 0x0200
|
||||
ftdi layout_signal nTRST -data 0x0100 -oe 0x0100
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# 2. JTAG Chain and Target Configuration
|
||||
# ----------------------------------------------------------------
|
||||
transport select jtag
|
||||
set _CHIPNAME riscv
|
||||
jtag newtap $_CHIPNAME cpu -irlen 5 ;# P550 has an IR length of 5
|
||||
|
||||
# Define the 4 P550 cores
|
||||
target create riscv.cpu0 riscv -chain-position $_CHIPNAME.cpu -coreid 0
|
||||
target create riscv.cpu1 riscv -chain-position $_CHIPNAME.cpu -coreid 1
|
||||
target create riscv.cpu2 riscv -chain-position $_CHIPNAME.cpu -coreid 2
|
||||
target create riscv.cpu3 riscv -chain-position $_CHIPNAME.cpu -coreid 3
|
||||
|
||||
# Group the cores for simultaneous operations like halt/resume
|
||||
target smp riscv.cpu0 riscv.cpu1 riscv.cpu2 riscv.cpu3
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# 3. Reset Configuration and Execution
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
# This is the key command. It tells OpenOCD that a "reset" should
|
||||
# assert (pull low) the nSRST signal.
|
||||
# srst_only: Asserts only nSRST, not nTRST (JTAG reset).
|
||||
# srst_pulls_trst: Informs OpenOCD that the board hardware ties nSRST and nTRST together.
|
||||
reset_config srst_only srst_pulls_trst
|
||||
|
||||
# Initialize OpenOCD and connect to the target
|
||||
init
|
||||
|
||||
# Halt the cores to gain control
|
||||
halt
|
||||
|
||||
# This command now triggers the nSRST signal as configured above.
|
||||
# It will pulse the reset line, causing a full hardware reboot.
|
||||
echo "!!! Pulsing system reset (nSRST) to reboot the board..."
|
||||
reset
|
||||
|
||||
# Optional: If you want the board to start running immediately after reboot
|
||||
# resume
|
||||
|
||||
# Exit OpenOCD
|
||||
shutdown
|
|
@ -0,0 +1,23 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"go.wit.com/lib/protobuf/chatpb"
|
||||
"go.wit.com/log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
filename := os.Args[1]
|
||||
// data, _ := os.ReadFile("log/sample.text")
|
||||
data, _ := os.ReadFile(filename)
|
||||
log.Info("trying unmarshal len(data) =", len(data))
|
||||
pb, err := chatpb.UnmarshalChatsTEXT(data)
|
||||
if err != nil {
|
||||
log.Info("Unmarshal error", err)
|
||||
// log.Info(string(data))
|
||||
return
|
||||
}
|
||||
|
||||
log.Info(pb.FormatTEXT())
|
||||
}
|
|
@ -28,4 +28,3 @@ func main() {
|
|||
time.Sleep(10 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
#!/bin/bash
|
||||
|
||||
# A script to automatically find and reset the FTDI USB-to-Serial converter
|
||||
# commonly used on SiFive development boards like the P550. This is useful
|
||||
# when a tool like OpenOCD takes exclusive control and doesn't release the
|
||||
# ttyUSB devices correctly.
|
||||
|
||||
set -e
|
||||
|
||||
# --- Configuration ---
|
||||
# The Vendor and Product ID for the FTDI FT4232H Quad-HS USB-UART/FIFO IC.
|
||||
# You can verify this for your board by running `lsusb`.
|
||||
VENDOR_ID="0403"
|
||||
PRODUCT_ID="6011"
|
||||
|
||||
# --- Sanity Checks ---
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo "This script must be run as root. Please use 'sudo'." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [ -d /sys/bus/usb/drivers/usb ]; then
|
||||
echo "Error: USB drivers not found at /sys/bus/usb/drivers/usb." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Main Logic ---
|
||||
echo "Searching for USB device with ID ${VENDOR_ID}:${PRODUCT_ID}..."
|
||||
|
||||
FOUND_BUS_ID=""
|
||||
for dir in /sys/bus/usb/devices/*; do
|
||||
if [ -f "${dir}/idVendor" ] && [ -f "${dir}/idProduct" ]; then
|
||||
if [ "$(cat "${dir}/idVendor")" == "${VENDOR_ID}" ] && [ "$(cat "${dir}/idProduct")" == "${PRODUCT_ID}" ]; then
|
||||
FOUND_BUS_ID=$(basename "${dir}")
|
||||
echo "Found SiFive board on USB bus ID: ${FOUND_BUS_ID}"
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -z "${FOUND_BUS_ID}" ]; then
|
||||
echo "Error: Could not find a connected SiFive board (FTDI ${VENDOR_ID}:${PRODUCT_ID})." >&2
|
||||
echo "Please ensure the board is connected." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Resetting USB device..."
|
||||
|
||||
# Unbind the device from the kernel
|
||||
echo " - Unbinding driver from ${FOUND_BUS_ID}..."
|
||||
echo -n "${FOUND_BUS_ID}" > /sys/bus/usb/drivers/usb/unbind
|
||||
|
||||
# Give it a moment to process
|
||||
sleep 1
|
||||
|
||||
# Bind the device, prompting the kernel to re-attach the driver
|
||||
echo " - Binding driver to ${FOUND_BUS_ID}..."
|
||||
echo -n "${FOUND_BUS_ID}" > /sys/bus/usb/drivers/usb/bind
|
||||
|
||||
echo "Done. The /dev/ttyUSB* devices should reappear shortly."
|
Loading…
Reference in New Issue